-
Notifications
You must be signed in to change notification settings - Fork 4.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
transport,grpc: Integrate delegating resolver and introduce dial options for target host resolution #7881
base: master
Are you sure you want to change the base?
Conversation
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #7881 +/- ##
==========================================
- Coverage 82.28% 82.24% -0.05%
==========================================
Files 381 385 +4
Lines 38539 38825 +286
==========================================
+ Hits 31712 31931 +219
- Misses 5535 5583 +48
- Partials 1292 1311 +19
|
7fa029c
to
619dcd4
Compare
internal/testutils/proxy.go
Outdated
} | ||
|
||
// NewProxyServer create and starts a proxy server. | ||
func NewProxyServer(lis net.Listener, requestCheck func(*http.Request) error, errCh chan error, doneCh chan struct{}, backendAddr string, resolutionOnClient bool, proxyServerStarted func()) *ProxyServer { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
may be we can do something like this fake server in its own package
// Package fakeserver provides a fake implementation of the management server. |
New should only create the object and StartServer/Run should start the go routine to accept requests
internal/transport/http2_client.go
Outdated
address := addr.Addr | ||
|
||
//if the ProxyConnectAddr is set in the aattribute, do a proxy dial. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typo: attribute
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
internal/transport/proxy.go
Outdated
func proxyDial(ctx context.Context, addr string, grpcUA string) (net.Conn, error) { | ||
newAddr := addr | ||
proxyURL, err := mapAddress(addr) | ||
// proxyDial dials, connecting to a proxy first if necessary. Dials, does the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we can remove the necessary part now? It will always dial proxy if called?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
Addr: "test-address", | ||
Attributes: attributes.New(userAndConnectAddrKey, attr{user: nil, addr: "proxy-address"}), | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nix new line
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
test/proxy_test.go
Outdated
|
||
// Tests grpc.NewClient with the default "dns" resolver and dial option | ||
// enabling target resolution on the client and verifies that the resolution | ||
// happens on client. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: mention the dial option WithTargetResolutionEnabled()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
test/proxy_test.go
Outdated
|
||
// Tests grpc.NewClient with grpc.WithNoProxy() set and verifies that it does | ||
// not dail to proxy, but directly to backend. | ||
func (s) TestGrpcNewClientWithNoProxy(t *testing.T) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
for the NoProxy and CustomDialer case, should we still override overrideHTTPSProxyFromEnvironment? That will make sure that even though proxy env is set we should skip it because of NoProxy and CustomDialer or is that not intended?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If WithNoProxy
or WithContextDialer
are set, the HTTPSProxyFromEnviornment
function will never be called, but we can still override and add error if it is being called. Is it a good practice to do so? @purnesh42H
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah so right now if HTTPSProxyFromEnviornment is not present, it doesn't matter if WithNoProxy
or WithContextDialer
is set? The resolution will happen at client anyways? So having it present and not being called in these two cases is what we want to verify.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
test/proxy_test.go
Outdated
} | ||
wantProxyAuthStr := "Basic " + base64.StdEncoding.EncodeToString([]byte(user+":"+password)) | ||
if got := req.Header.Get("Proxy-Authorization"); got != wantProxyAuthStr { | ||
gotDecoded, _ := base64.StdEncoding.DecodeString(got) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we should not ignore decoding errors. it should return error if decoding fails
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
internal/testutils/proxy.go
Outdated
}() | ||
t.Logf("Started proxy at: %q", pLis.Addr()) | ||
t.Cleanup(p.stop) | ||
p.Addr = fmt.Sprintf("localhost:%d", ParsePort(t, pLis.Addr().String())) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also why can't this just be pLis.Addr().String()
? There should be a comment explaining why it's doing all this extra stuff to seemingly just convert localhost:123
into localhost:123
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pLis..Addr()
will be a IP address, we convert it to localhost:port
to make sure the DNS resolver is working correctly for the proxy and connecting to the proxy server.
internal/transport/proxy.go
Outdated
u := t.Username() | ||
p, _ := t.Password() | ||
|
||
if user := opts.User; user != (url.Userinfo{}) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comparison with a zero-initialized Userinfo looks a little off to me. Should this field in opts
be a pointer instead to determine whether it was set intentionally?
Or should it check if either Username()
or Password()
are non-empty?
I'm not sure exactly what the right behavior is, but this seems questionable, as it's including any unexported fields in the comparison.
Related but potential existing problem to investigate: what if username is set but password is not? Is that valid? If so, is the proper behavior to encode it as username:
, as it does currently, or should the :
be omitted?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The RFC doesn't clearly mention what is the correct syntax if password is absent , so I think either way should be fine, but adding a semicolon like username:
would be more explicit in indication username has ended and the password is empty.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have added a UserSet
option as changing it to a pointer can allow the caller to modify the use info.
Fixes: #7556
RELEASE NOTES:
WithTargetResolutionEnabled()
dial option added to explicitly force target URI resolution on the client.